package com.zyy.joseata.interceptor;

import com.zyy.joseata.annotation.JoCancel;
import com.zyy.joseata.annotation.JoConfirm;
import com.zyy.joseata.bo.TxClazzBO;
import com.zyy.joseata.util.JoSeataContextUtil;
import com.zyy.joseata.util.ThreadLocalUtil;
import com.zyy.joseata.util.TxClazzMapUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author zhangyy
 */
@Aspect
@Component
@Slf4j
@Order(-1)
public class JoTryInterceptor {

    @Around("@annotation(com.zyy.joseata.annotation.JoTry)")
    public Object aroundJoTry(ProceedingJoinPoint joinPoint) throws Throwable {
        Class<?> clazz= joinPoint.getTarget().getClass();
        TxClazzBO txClazz = TxClazzMapUtil.getClazz(clazz);
        if(txClazz == null){
            parseConfirmAndCancelMethod(clazz);
            txClazz = TxClazzMapUtil.getClazz(clazz);
        }

        if(ThreadLocalUtil.getTxId() == null){
            if(JoSeataContextUtil.getTxId() != null){
                ThreadLocalUtil.setTxId(JoSeataContextUtil.getTxId());
            }
        }

        TxClazzMapUtil.setTxClazz(ThreadLocalUtil.getTxId(),txClazz);

        // 执行原本方法
        Object result = joinPoint.proceed();
        return result;
    }

    /**
     * 解析class的confirm和cancel方法
     * @param clazz
     */
    private void parseConfirmAndCancelMethod(Class<?> clazz) {
        Method[] methods = clazz.getDeclaredMethods();
        Method confirmMethod = null,cancelMethod=null;

        for(Method method:methods) {
            if(method.isAnnotationPresent(JoConfirm.class)){
                confirmMethod = method;
            }else if(method.isAnnotationPresent(JoCancel.class)){
                cancelMethod = method;
            }
            if(confirmMethod != null && cancelMethod != null){
                break;
            }
        }

        TxClazzMapUtil.setClazzMethod(clazz,confirmMethod,cancelMethod);
    }
}
